/**
 * @file otdr_ch.h
 * @synopsis  定义描述otdr通道资源的头文件
 * @author wen wjcapple@163.com
 * @version 2.0
 * @date 2016-06-23
 */
#ifndef _OTDR_CH_H_
#define _OTDR_CH_H_

#include <stdint.h>
#include <pthread.h>
#include <semaphore.h>

#include "tmsxx.h"
#include "otdrtestinterface.h"
#include "otdrfindalarm.h"
//声明otdr算法中定义的全局变量


#ifdef __cplusplus
extern "C" {
#endif


#define DATA_LEN	16000
//#define CH_NUM		2 /* 通道数目*/
/*
 * 像告警指示之类和通道数目相关，只有几个字节，动态分配
 * 不划算，因此设置一个通道数目天花板，如果支持的通道数目超过
 * 宏定义值，需要进行修改
*/
enum {NONE = 0, PWU, MCU, OPM, OSW, OTDR, OLS,OLP,GSM,TU};
#define CH_NUM_CEIL		32 
#define CH_MIN		0	//最小通道编号
#define CH_MAX		8	//最大通道编号	
#define FRAME_MIN	0	//槽位的最小编号
#define FRAME_MAX	15	//槽位的最大编号
#define SLOT_MIN	0	//槽位的最小编号
#define SLOT_MAX	256	//槽位的最大编号
//通道缓冲区交叉使用，0，2通道对应对应0缓冲区，1，3通道使用1缓冲
#define CH_BUF_NUM	2 //串行测试，2个缓冲区即可
#define MEASURE_TIME_MIN_MS	7000 /*最小测试时间*/	
#define MEASURE_TIME_MIN_S	(MEASURE_TIME_MIN_MS / 1000)
#define OTDR_TEST_MOD_MONITOR		0	//监测模式
#define OTDR_TEST_MOD_USR		1	//点名测量
//定义操作码
#define OP_OK	0
//文件操作返回码
#define OPEN_ERROR	1  //打开文件失败
#define SAVE_DATA_LEN_NO_EQ	2	//写入的数据长度和要写入的不相等
#define READ_DATA_LEN_ERROR	3	//读取文件长度错误
#define FILE_RUIN		4	//文件损坏	
#define NEW_BUF_FAIL		5	//分配内存失败:w
	//#pragma pack (1) /*按照1B对齐*/
#define LOCK_TYPE_SPIN
//定义快速锁 万一有什么问题，直接在这里修改定义
#ifdef LOCK_TYEP_SPIN
	//自旋转锁
	typedef pthread_spinlock_t QUICK_LOCK; 
#else
	//带任务切换的互斥量
	typedef pthread_mutex_t QUICK_LOCK; 
#endif
#define OTDR_TEST_MONITOR	0	//监控测量
#define OTDR_TEST_USR		1	//用户指定测量
#define OTDR_CH_ON		1	//通道可操作
#define OTDR_CH_OFF		0	//通道不可操作
//描述通道控制参数
#define CHCTRL_FIXED_BYTES	12	//初始化的时候，前面多少个字节不能设置成0，是根据配置命令
struct _tagSecLossVal
{
	float len;
	float loss;
};
#define LOSS_SEC_NUM  10
struct _tagSecLoss
{
	int32_t sec_num;
	float alarm_dis;	//B标杆的距离*告警比例
	struct _tagSecLossVal val[LOSS_SEC_NUM];
};

struct _tagCHCtrl
{
	int32_t enable;		//是否启用
	int32_t is_cfged;	//是否配置
	int32_t refresh_para;	//更新光纤段参数
	/*下面的代码部分初始化部分要赋值成0*/
	int32_t mod;		//0,轮询，1点名测量
	int32_t st_fiber_len;  //标准曲线的光线长度，用来判断是否切换脉宽
	int32_t st_pulse;  //标准曲线的光线长度，用来判断是否切换脉宽
	int32_t cur_fiber_len;//记录当前光纤长度
	int32_t test_count;	//记录测试次数，每次更新监测参数复位
	int32_t lamda;		//波长
	int32_t	lamda_type;	//激光器波长
	int32_t dyna;		//动态
	int32_t is_small_pl_test; //是否使用小脉宽测试
	struct _tagSecLoss sec_loss;
};
//描述otdr通道状态
struct _tagCHState
{
	int32_t algro_run;	//算法运行状态，0表示算法运行结束
	int32_t resource_id;	//资源id，tsk_otdr保留一个副本
	int32_t success_num;	//测试成功的计数
	int32_t fail_num;	//测试失败的计数
	int32_t spi_error_num;	//spi通信失败的次数
	int32_t ch_buf_collid_num;	//ch buf 访问冲突的次数
	int32_t algro_collid_num;	//算法线程访问冲突的次数
	int32_t lamda_usr;


};
//通道的测量参数
struct _tagCHPara
{
	uint32_t Lambda_nm;		// 波长，单位nm
	uint32_t MeasureLength_m;	// 量程，单位m
	uint32_t PulseWidth_ns;		// 光脉冲宽度，单位ns
	uint32_t MeasureTime_ms;	// 测量时间，单位ms
	float n;                  	// 折射率

	float   EndThreshold;       // 结束门限
	float   NonRelectThreshold; // 非反射门限;
};
//激光器控制参数
struct _tagLaserCtrPara
{
	int32_t rcv;
	int32_t power;
	int32_t apd;
	int32_t trail_length;
};
//通道缓存区，存放高低功率的累加数据
struct _tagCHBuf
{
	int32_t hp_buf[DATA_LEN];	//高功率曲线buf
	int32_t lp_buf[DATA_LEN];	//低功率曲线buf
};
//上报时使用的otdr参数,下面配置的时候会多20个字节的标志，sb
struct _tagUpOtdrPara
{
	int32_t slot;	//槽位
	int32_t pipe;//通道
	int32_t rang_m;	//量程
	int32_t lamda_nm;	//波长
	int32_t pl;	//脉宽
	int32_t test_time_s;	//测试时间
	float gi;	//折射率
	float end_th;	//结束门限门限
	float no_ref_th;//非反射门限
	int32_t sampl_hz;
	int32_t rsv2;
	int32_t rsv3;

};
//测量结果
struct _tagUpOtdrTestResult
{
	char id[20];	//标志
	float chain;	//链长
	float loss;	//链损耗
	float attu;	//衰减
};
struct _tagOtdrEvent
{
	int32_t distance;
	int32_t type;
	float attu;
	float insert_loss;
	float return_loss;
	float total_loss;
};
struct _tagUpOtdrEvent
{
	char id[12];
	int32_t num;
	struct _tagOtdrEvent buf[MAX_EVENT_NUM];
};
struct _tagUpOtdrData
{
	char id[12];
	int32_t num;
	uint16_t buf[DATA_LEN];
};

//上传曲线结构
struct _tagUpOtdrCurv
{
	struct _tagUpOtdrPara para;
	struct _tagUpOtdrTestResult result;
	struct _tagUpOtdrData data;
	struct _tagUpOtdrEvent event;
};

//周期性测量曲线,每个测试完毕，就更新一次
struct _tagCycCurv
{
	QUICK_LOCK lock;
	struct _tagUpOtdrCurv curv;
};
//otdr设备，包含描述该设备的其他结构体变量
struct _tagOtdrDev
{
	sem_t sem_msg;				//消息信号量
	struct _tagCHCtrl ch_ctrl;		//通道控制状态
	struct _tagCHPara ch_para;		//通道的参数
	struct _tagCHPara appoint_para;		//点名测量参数
	struct _tagCycCurv curv;		//周期性测量曲线buf


};
//并行otdr控制变量
struct _tagParalleCtrl
{
	DeviceInfo_t device;			//fpga设备,每个通道相当于一个独立的
	pthread_mutex_t mutex_tsk;		//任务锁
	sem_t sem_appoint;			//点名测量信号量
	int32_t stop;				//停止测量
};
//算法运行的时候一些指示信息
struct _tagAlgroCHInfo
{
	int32_t cmd;	//命令码
	int32_t state;	//0 空闲，1正忙
	int32_t ch;	//通道号
	int32_t resource_id;	//资源id
	int32_t mod;	//测试方式 点名测量，轮询
	int32_t src_addr; //如果是点名测量，用来指示数据发向哪里
	int32_t lamda_usr; //用户的波长
};
struct _tagAlarm
{
	int32_t ch;	//通道号
	int32_t sec;	//光线段号
	int32_t lev;	//级别
	int32_t type;	//告警类型
	float loss_diff;
	int32_t pos[3];	//位置
	int32_t error_distance;	//保留项
};
//光线段告警
struct _tagSecFiberAlarm
{
	int32_t ch;
	int32_t chang;
	int32_t alarm_num;
	int32_t sec_num;
	struct _tagAlarm *buf;
	struct _tagUpOtdrCurv *pcurv;
};
struct _tagSecStatisData
{
	int32_t sec;
	float attu;
};
//光纤段统计数据,在读取文件的时候分配
struct _tagFiberStatisData
{
	int32_t state;		/*状态，0，ok，其他出现错误*/
	int32_t counts;		/*计数，当前数据是第几次更新*/
	int32_t ch;		/*通道号*/
	int32_t sec_num;	/*段的数目*/
	struct _tagSecStatisData *buf;
};


//与tms_fibersectioncfg的差别是将固定长度的变量设置成了非指针
struct _tagFiberSecCfg
{
	struct tms_fibersection_hdr fiber_hdr; //光纤段头
	struct tms_fibersection_val *fiber_val;//光纤段信息
	struct tms_otdr_param       otdr_param;//otdr参数
	struct tms_test_result      test_result;//测量结果
	struct tms_hebei2_data_hdr  otdr_hdr;//采样点数据头
	struct tms_hebei2_data_val  *otdr_val;//otdr数据部分
	struct tms_hebei2_event_hdr event_hdr;//时间点头
	struct tms_hebei2_event_val *event_val;//时间点缓冲区
	int32_t is_initialize;
	int32_t error_num;
};
//每个光线段 段告警，包含告警次数
struct _tagSecAlarm
{
	int32_t occur_count;		//产生次数
	int32_t fade_count;		//消失次数
	FiberAlarm_t alarm;	//告警,里面的
};
//每个通道的告警缓存
struct _tagCHAlarmCache
{
	int32_t sec_num;	//总的段号
	int32_t test_num;	//如果产生或者消失次数小于触发次数的时候开始计数
	struct _tagSecAlarm *palarm;	//告警缓冲区
};
//模块适应部分
struct _tagAlarmModuleAdpt
{
	int32_t is_initial; 	//初始化标志
	int32_t sec_num; 	//光线段总数
	int32_t max_sec_num;

	OTDRCurveInfo_t  std_curv;		//标准曲线
	float data_buf[DATA_LEN];	//数据点+5
	OTDREvent_t event_buf[MAX_EVENT_NUM];	//事件缓冲区
	FiberSectionByEvent_t event_sec_buf[MAX_EVENT_NUM];	//光线段缓冲区
	FiberSegmentInfo_t fiber_sec;		//光线段
	FiberAlarmInfo_t cur_alarm; 		//告警信息，每次调用传入
	struct _tagCHAlarmCache alarm_cache;		//告警缓存，判断最终是否产生告警
};

//需要加锁
struct _tagCHFiberSec
{
	QUICK_LOCK lock;			//同步锁
	struct _tagFiberSecCfg para;		//光线段配置参数
	struct _tagFiberStatisData statis;	//统计数据
	struct _tagSecFiberAlarm alarm;		//协议告警
	struct _tagAlarmModuleAdpt adpt_moudle; //告警模块适配
};
//设备状态
struct _tagDevState
{
	int32_t on_use;//处于启用的状态
	int32_t error_state;
};
#define USR_OTDR_TEST_IDLE	36	//点名测量空闲，可以点名测量
#define USR_OTDR_TEST_WAIT	1	//正在等待测量
#define USR_OTDR_TEST_ACCUM	2	//正处于累加中，不能响应点名测量
#define USR_OTDR_TEST_ALGRO	3	//正处于找时间点的中，
struct _tagFrameAddr 
{
	uint32_t src;		///< 本地地址
	uint32_t dst;		///< 目的地址
	uint16_t pkid;      ///< 该包的pkid 为了给上层提供修改序列号的权利
};
//通道相关的信息，包括激光器波长，动态范围等相关硬件信息
struct _tagFpgaPara
{
	int32_t slot;
	int32_t ch;
	int32_t lamda;
	int32_t scope_dB;
	char wdm[16];
	int32_t option;

};
//通道信息
struct _tagCHInfo
{
	int32_t num; //是否初始化标志 0，未初始化，1初始化
	struct _tagFpgaPara *para;
};	
//节点名称和地址
struct _tagDevNameAddr
{
	char name[64];
	char ip[16];
	char mask[16];
	char gate[16];
};
struct _tagDevCHState
{
	int32_t state;
};
//杂项，乱七八糟
struct _tagDevMisc
{ 
	struct _tagDevNameAddr name;
	struct _tagDevCHState ch_state;
};
//保存线程sys_id ,htop id htop id 主要用来查看线程占用率
struct _tagThreadInfo
{
	pthread_t tid;	//create_thread 赋值
	int32_t top_id;	//线程自身赋值
	int32_t ch;	//通道编号，并行otdr有用，如果是串行otdr忽略
};
struct _tagOtdrAlgroPara
{
	struct _tagAlgroCHInfo *pCHInfo;

};
struct _tagVersion
{
	char hw[12];
	char soft[12];
};
//检测到网段发生改变，时在一个读取周期内再读一次，如果两次相同，检查网络ip
//是否和网段一致
#define CTRL_SW_IP_NUM  2
#define CTRL_SW_FRAME_NUM 2 
struct _tagIpSwitchCtr
{
	int32_t flag; 	//网段标志
	int32_t count;	//网段计数
	int32_t frame;	//机框号
	int32_t countF;	//机框号计数
	int32_t re_connect; //重连CU
};
struct _tagCtrlPkid
{
	int16_t pkid;
	QUICK_LOCK lock;
};
//定义主机协议使用的参数基本部分,上传部分包含了一些无聊的字符串

struct _tagHostOtdrPara
{
	int32_t slot;			//槽位
	int32_t pipe;			//通道
	int32_t MeasureLength_m;	// 量程，单位m
	int32_t Lambda_nm;		// 波长，单位nm
	int32_t PulseWidth_ns;		// 光脉冲宽度，单位ns
	int32_t MeasureTime_s;	// 测量时间，单位ms
	float n;                  	// 折射率

	float   EndThreshold;       // 结束门限
	float   NonRelectThreshold; // 非反射门限;
	int32_t sample_hz;
	int32_t rsv2;
	int32_t rsv3;

};
//点名测量结构体
struct _tagUsrOtdrTest
{
	uint32_t state;		//空闲？累加？找事件点？
	uint32_t cmd;		//0x80*014/0x80*15 点名测量，配置测量
	struct _tagFrameAddr src_addr;	//操作设备的地址
	uint32_t initial;	//点名测量前抢占的的通道

	struct _tagHostOtdrPara para;
	struct tms_dev_desc osw; //2017-09-28 维纳迪增加光开关
};

//typedef struct _tagUpOtdrPara _tagHostOtdrPara;
struct _tagHostTestResult
{
	float chain;	//链长
	float loss;	//链损耗
	float attu;	//衰减
};
#define OTDR_SERRI	2 	//串行otdr	
#define OTDR_PARALLE	1	//并行otdr
struct _tagOtdrTestCtrl
{
	int32_t stop;
	int32_t is_send_alarm;	//是否发送告警
	int32_t monitor_num;	//监测通道数目
	int32_t pause_cyc; //暂停监测,处理点名测量之类的
	int32_t mod;		//0,串行，1并行
	int32_t ch_num;		//通道数目
	int32_t alarm_syn;	//告警同步，并行otdr只有所有的通道都检查完毕，才会向上发送告警
	int32_t monitor_over;	//监测完成，该值等于pow(2,ch_num)-1,用alarm_syn中的一位来指示是否监测完成
	int32_t apponit_ch;

};
typedef DeviceInfo_t _tagSpiDevCtrl; 
/*
#define GPIO_NUM_SLOT	4
#define GPIO_NUM_CH_ALARM	4	
*/
struct _tagGpioFd
{
	int32_t is_ok;
	int32_t frame[48];	//机框
	int32_t slot[48];	//槽位
	int32_t alarm_ch[64];	//通道告警指示 
	//int32_t alarm_commu;	//通信告警
	int32_t alarm_total;	//总的告警CU的fd
	int32_t alarm_total_1;	//总的告警本地的fd
	int32_t ip_flag;	//网段标志
	int32_t run;		//运行指示
};
struct _tagCHAlarmDis
{
	int32_t alarm_num;
	int32_t ch[CH_NUM_CEIL];

};
struct _tagCuState
{
	int32_t state;
	int32_t fail_count;
};
//板卡类型
struct _tagCardAttribute
{
	int32_t slot;
	int32_t type;
};
struct _tagDynaPulse
{
	int32_t dyna;
	int32_t pulse;
};
#define DYNA_PULSE_NUM		8	
struct _tagPulseHouse
{
	int32_t num;
	struct _tagDynaPulse cdp[DYNA_PULSE_NUM];
	struct _tagDynaPulse pdp[DYNA_PULSE_NUM];
};
struct _tagTickCount
{
	int32_t src_e;
};
//#pragma pack () /*恢复默认的对其方式*/ 
#ifdef __cplusplus
}
#endif

#endif

